package org.ptkparty.shared.model;

import java.util.Date;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Query;
import javax.persistence.Version;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

import org.datanucleus.api.jpa.annotations.Extension;
import org.ptkparty.server.dao.EMFService;
import org.ptkparty.server.service.MailService;

import com.google.api.services.plus.model.Person;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserServiceFactory;

@Entity
public class UserEntity {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
	private String id;

	@Version
	private Integer version;

	@NotNull
	private String nickname;

	@NotNull
	@Pattern(regexp = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$", message = "E-mail non valide")
	private String email;

	private String googlePlusToken;

	private String cover;

	private String image;

	private Date dateCreation;

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public Integer getVersion() {
		return version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	@SuppressWarnings("unchecked")
	public static List<UserEntity> getAllUser() {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			List<UserEntity> users = em.createQuery("SELECT u from UserEntity u ORDER BY u.nickname").getResultList();
			users.size();
			return users;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static List<UserEntity> getUsersByChampionship(String championship) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			List<UserEntity> users = em.createQuery("SELECT u from UserEntity u WHERE u.id IN (:ids) ORDER BY u.nickname") //
					.setParameter("ids", ChampionshipEntity.findChampionshipEntity(championship).getUsers()) //
					.getResultList();
			users.size();
			return users;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		return null;
	}

	public static UserEntity findUserEntity(String id) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			return em.find(UserEntity.class, id);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	public static UserEntity getUser(String email) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			Query query = em.createQuery("SELECT u from UserEntity u WHERE u.email = :email");
			query.setParameter("email", email);
			List<UserEntity> result = query.getResultList();

			if (result != null && result.size() != 0) {
				return (UserEntity) result.get(0);
			}

			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			em.close();
		}
	}

	public static UserEntity getCurrentUser() {
		try {
			return getUser(UserServiceFactory.getUserService().getCurrentUser().getEmail());
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	public static UserEntity updateUser(User user) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			UserEntity userEntity = getUser(user.getEmail());
			if (userEntity == null) {
				userEntity = new UserEntity();
				userEntity.setNickname(user.getNickname());
				userEntity.setEmail(user.getEmail());
				userEntity.setDateCreation(new Date());
				em.persist(userEntity);

				MailService.getInstance().sendWelcomeEmail(userEntity);
			}

			return userEntity;

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			em.close();
		}
	}

	private void setDateCreation(Date dateCreation) {
		this.dateCreation = dateCreation;
	}

	public void persist() {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			if (getId() == null) {
				em.persist(this);
			} else {
				em.merge(this);
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
	}

	public void remove() {
		if (this.getId() != null) {
			EntityManager em = EMFService.get().createEntityManager();
			try {
				em.remove(em.merge(this));
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				em.close();
			}
		}
	}

	public static void save(List<UserEntity> users) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			for (UserEntity user : users) {
				if (user.getId() == null) {
					em.persist(user);
				} else {
					em.merge(user);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
	}

	public String getNickname() {
		return nickname;
	}

	public void setNickname(String nickname) {
		this.nickname = nickname;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public static void updateUser(Person me, String token) {
		if (me != null) {
			EntityManager em = EMFService.get().createEntityManager();
			try {
				UserEntity userEntity = getUser(UserServiceFactory.getUserService().getCurrentUser().getEmail());

				userEntity.setNickname(me.getDisplayName());
				if (me.getImage() != null) {
					userEntity.setImage(me.getImage().getUrl());
				}
				if (me.getCover() != null) {
					userEntity.setCover(me.getCover().getCoverPhoto().getUrl());
				}

				userEntity.setGooglePlusToken(token);

				em.merge(userEntity);

			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				em.close();
			}
		}
	}

	private void setGooglePlusToken(String token) {
		this.googlePlusToken = token;
	}

	private void setCover(String url) {
		this.cover = url;
	}

	private void setImage(String url) {
		this.image = url;
	}

	public String getGooglePlusToken() {
		return googlePlusToken;
	}

	public String getCover() {
		return cover;
	}

	public String getImage() {
		return image;
	}

	public Date getDateCreation() {
		return dateCreation;
	}

}
